<template>
    <div class="file-upload-container">
        <!-- 左侧文件上传区域 -->
        <el-card class="upload-section">
            <div class="upload-header">
                <h3>选择文件</h3>
            </div>

            <!-- 文件拖拽上传区域 -->
            <div class="upload-area" @drop="handleDrop" @dragover="handleDragOver" @dragleave="handleDragLeave">
                <div class="upload-icon">
                    <el-icon :size="48" color="#409EFF">
                        <FolderOpened />
                    </el-icon>
                </div>
                <div class="upload-text">
                    <p class="main-text">拖拽文件到此处上传</p>
                    <p class="sub-text">
                        支持单个或批量上传，支持 PDF、Word、Excel、PPT、图片、视频、音频、文本、压缩包等格式
                    </p>
                </div>
                <el-button type="primary" @click="selectFiles">选择文件</el-button>
                <input ref="fileInput" type="file" multiple style="display: none" @change="handleFileSelect" />
            </div>

            <!-- 已选择的文件列表 -->
            <div v-if="selectedFiles.length > 0" class="selected-files">
                <div class="files-header">
                    <h4>已选择的文件 ({{ selectedFiles.length }})</h4>
                    <el-button type="text" @click="clearAllFiles">清空全部</el-button>
                </div>
                <div class="files-list">
                    <div v-for="(file, index) in selectedFiles" :key="index" class="file-item">
                        <div class="file-icon">
                            <el-icon :size="24" :class="getFileIconClass(file.type)">
                                <component :is="getFileIcon(file.type)" />
                            </el-icon>
                        </div>
                        <div class="file-info">
                            <div class="file-name" :title="file.name">{{ file.name }}</div>
                            <div class="file-meta">
                                <span class="file-size">{{ formatFileSize(file.size) }}</span>
                                <span class="file-type">{{ getFileTypeText(file.type) }}</span>
                                <span v-if="file.duration" class="file-duration">{{
                                    formatDuration(file.duration)
                                    }}</span>
                                <span v-if="file.isAvi" class="file-format">AVI</span>
                            </div>
                        </div>
                        <div class="file-actions">
                            <el-button type="text" size="small" @click="removeFile(index)">
                                <el-icon>
                                    <Close />
                                </el-icon>
                            </el-button>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 上传须知 -->
            <div class="upload-notice">
                <el-alert title="上传须知" type="info" :closable="false" show-icon>
                    <ul class="notice-list">
                        <li>请确保文件内容合规，不包含敏感信息</li>
                    </ul>
                </el-alert>
            </div>
        </el-card>

        <!-- 右侧文件信息区域 -->
        <el-card class="info-section">
            <div class="info-header">
                <h3>文件信息</h3>
            </div>

            <!-- 文件分类 -->
            <div class="form-item">
                <label class="form-label required">文件分类</label>
                <div class="category-section">
                    <CategorySelector ref="categorySelectorRef" v-model="selectedCategoryIds" :multiple="false"
                        placeholder="请选择文件分类" width="100%" @change="handleCategoryChange" />
                </div>
            </div>
            <!-- 操作按钮 -->
            <div class="action-buttons">
                <el-button @click="resetForm" :disabled="uploading">重置</el-button>
                <el-button type="primary" @click="handleBatchUpload" :disabled="selectedFiles.length <= 0 || selectedCategoryIds.length <= 0 || uploading
                    " :loading="uploading">
                    {{ uploading ? '提交中...' : '点击提交' }}
                </el-button>
            </div>
        </el-card>

        <!-- 上传进度弹窗 -->
        <el-dialog v-model="progressModalVisible" title="文件上传进度" width="700px" :close-on-click-modal="false"
            :close-on-press-escape="false" :show-close="uploadingFiles.length === 0">
            <div class="upload-progress-container">
                <el-table :data="uploadingFiles" style="width: 100%" :show-header="true">
                    <el-table-column prop="name" label="文件名" width="180">
                        <template #default="{ row }">
                            <div class="file-name-cell">
                                {{ row.name }}
                            </div>
                        </template>
                    </el-table-column>

                    <el-table-column prop="size" label="大小" width="120">
                        <template #default="{ row }">
                            {{ formatFileSize(row.file.size) }}
                        </template>
                    </el-table-column>

                    <el-table-column label="类型/时长" width="100">
                        <template #default="{ row }">
                            <div class="file-type-info">
                                <div>{{ getFileTypeText(row.type) }}</div>
                                <div v-if="row.duration" class="duration-text">
                                    {{ formatDuration(row.duration) }}
                                </div>
                                <div v-if="row.isAvi" class="avi-badge">AVI</div>
                            </div>
                        </template>
                    </el-table-column>

                    <el-table-column label="进度" min-width="180">
                        <template #default="{ row }">
                            <div class="progress-cell">
                                <el-progress :percentage="row.progress" :status="row.status === 'error'
                                    ? 'exception'
                                    : row.status === 'success'
                                        ? 'success'
                                        : undefined
                                    " :stroke-width="8">
                                    <template #default="{ percentage }">
                                        <span class="progress-text">
                                            {{ percentage }}%
                                            <span v-if="row.totalChunks > 0">
                                                ({{ row.currentChunk }}/{{ row.totalChunks }})
                                            </span>
                                        </span>
                                    </template>
                                </el-progress>
                            </div>
                        </template>
                    </el-table-column>
                </el-table>
            </div>

            <template #footer>
                <div class="dialog-footer">
                    <el-button type="primary" @click="progressModalVisible = false">
                        确定
                    </el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'
import {
    FolderOpened,
    Close,
    Document,
    Picture,
    VideoPlay,
    Headset,
    Files
} from '@element-plus/icons-vue'

import SparkMD5 from 'spark-md5'
import axios from 'axios'
import { initUpload, completeUpload, batchAdd } from '@/api/uploads'
import CategorySelector from '@/components/category-selector/index.vue'

// CategorySelector组件引用
const categorySelectorRef = ref<InstanceType<typeof CategorySelector>>()

// 接口类型定义
interface FileInfo {
    category: string
    tags: string[]
    description: string
}

interface UploadFile {
    name: string
    size: number
    type: string
    file: File
    progress?: number
    status?: 'waiting' | 'uploading' | 'success' | 'error'
    currentChunk?: number
    totalChunks?: number
    md5?: string
    uploadId?: string
    ossPath?: string // OSS文件路径
    objectName?: string
    duration?: number // 视频时长（秒）
    isAvi?: boolean // 是否为AVI格式
}

// 响应式数据
const fileInput = ref<HTMLInputElement>()
const uploading = ref(false)
const customTag = ref('')
const progressModalVisible = ref(false)
const uploadingFiles = ref<UploadFile[]>([])
const selectedCategoryIds = ref<string[]>([])

// 移除静态分类数据，现在使用CategorySelector组件

// 文件信息表单
const fileInfo = reactive<FileInfo>({
    category: '',
    tags: [],
    description: ''
})

// 选中的文件列表
const selectedFiles = ref<UploadFile[]>([])

/**
 * 处理分类选择变化
 */
const handleCategoryChange = (ids: string[], categories?: any[]) => {
    selectedCategoryIds.value = ids
    console.log('选中的分类ID:', ids)
    console.log('选中的分类详情:', categories)
}



/**
 * 选择文件
 */
const selectFiles = () => {
    fileInput.value?.click()
}

/**
 * 获取视频时长
 */
const getVideoDuration = (file: File): Promise<number> => {
    return new Promise((resolve) => {
        const video = document.createElement('video')
        video.preload = 'metadata'

        video.onloadedmetadata = () => {
            window.URL.revokeObjectURL(video.src)
            resolve(video.duration || 0)
        }

        video.onerror = () => {
            window.URL.revokeObjectURL(video.src)
            resolve(0)
        }

        video.src = URL.createObjectURL(file)
    })
}

/**
 * 检查是否为AVI格式
 */
const checkIsAvi = (file: File): boolean => {
    return file.name.toLowerCase().endsWith('.avi') || file.type === 'video/x-msvideo'
}

/**
 * 处理文件选择
 */
const handleFileSelect = async (event: Event) => {
    const target = event.target as HTMLInputElement
    const files = target.files

    if (files && files.length > 0) {
        // 处理文件并立即开始上传
        await processFiles(Array.from(files))

        // 清空input的值，允许重复选择相同文件
        target.value = ''

        // 立即开始上传
        await startAutoUpload()
    }
}

/**
 * 处理拖拽放置
 */
const handleDrop = async (event: DragEvent) => {
    event.preventDefault()
    const files = event.dataTransfer?.files

    if (files && files.length > 0) {
        // 处理文件并立即开始上传
        await processFiles(Array.from(files))

        // 立即开始上传
        await startAutoUpload()
    }
}

/**
 * 处理拖拽悬停
 */
const handleDragOver = (event: DragEvent) => {
    event.preventDefault()
}

/**
 * 处理拖拽离开
 */
const handleDragLeave = (event: DragEvent) => {
    event.preventDefault()
}

/**
 * 处理文件列表
 */
const processFiles = async (files: File[]) => {
    const validFiles: UploadFile[] = []

    for (const file of files) {
        // 检查文件类型
        const allowedTypes = [
            'application/pdf',
            'application/msword',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/vnd.ms-excel',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'application/vnd.ms-powerpoint',
            'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            // 压缩包格式 - 支持多种MIME类型
            'application/zip',
            'application/x-zip-compressed',
            'application/octet-stream', // 某些系统可能将zip识别为此类型
            'application/x-rar-compressed',
            'application/x-rar',
            'application/x-7z-compressed', // 7z格式
            // 文本格式
            'text/plain',
            'text/html',
            'text/css',
            'text/javascript',
            'text/xml',
            'application/json',
            'application/xml',
            'text/csv',
            'text/markdown',
            // 视频格式
            'video/mp4',
            'video/avi',
            'video/mov',
            'video/wmv',
            'video/flv',
            'video/webm',
            'video/mkv',
            'video/3gp',
            'video/x-msvideo'
        ]

        const isImageType = file.type.startsWith('image/')
        const isVideoType = file.type.startsWith('video/') || checkIsAvi(file)
        const isAudioType = file.type.startsWith('audio/')
        const isTextType = file.type.startsWith('text/') || file.type === 'application/json' || file.type === 'application/xml'
        const isAllowedType = allowedTypes.includes(file.type)

        // 基于文件扩展名的额外检查（处理MIME类型不准确的情况）
        const fileName = file.name.toLowerCase()
        const isZipByExtension = fileName.endsWith('.zip')
        const isRarByExtension = fileName.endsWith('.rar')
        const is7zByExtension = fileName.endsWith('.7z')
        const isArchiveByExtension = isZipByExtension || isRarByExtension || is7zByExtension

        if (!isImageType && !isVideoType && !isAudioType && !isTextType && !isAllowedType && !isArchiveByExtension) {
            ElMessage.warning(`文件 ${file.name} 格式不支持`)
            continue
        }
        console.log('文件信息:', {
            name: file.name,
            type: file.type,
            size: file.size,
            isArchiveByExtension,
            isAllowedType
        })

        const uploadFile: UploadFile = {
            name: file.name,
            size: file.size,
            type: file.type,
            file,
            status: 'waiting',
            progress: 0,
            currentChunk: 0,
            totalChunks: 0,
            isAvi: checkIsAvi(file)
        }

        // 如果是视频文件，获取时长
        if (isVideoType) {
            try {
                uploadFile.duration = await getVideoDuration(file)
            } catch (error) {
                console.warn('获取视频时长失败:', error)
                uploadFile.duration = 0
            }
        }

        validFiles.push(uploadFile)
    }

    // 追加到现有文件列表而不是替换
    selectedFiles.value = [...selectedFiles.value, ...validFiles]

    if (validFiles.length > 0) {
        ElMessage.success(
            `已选择 ${validFiles.length} 个文件，总计 ${selectedFiles.value.length} 个文件`
        )
    }
}

/**
 * 上传单个文件（分片上传）
 */
const uploadSingleFile = async (uploadFile: UploadFile, fileIndex: number) => {
    console.log('uploadFile', uploadFile)

    const chunkSize = 10 * 1024 * 1024 // 10MB分片大小
    const totalChunks = Math.ceil(uploadFile.file.size / chunkSize)

    // 更新文件状态
    uploadingFiles.value[fileIndex].status = 'uploading'
    uploadingFiles.value[fileIndex].totalChunks = totalChunks

    try {
        // 计算文件MD5
        const fileMd5 = await calculateFileMD5(uploadFile.file)
        uploadingFiles.value[fileIndex].md5 = fileMd5

        // 准备上传参数
        const uploadParams = {
            filename: uploadFile.name,
            partCount: totalChunks,
            md5: fileMd5,
            category: fileInfo.category,
            tags: fileInfo.tags,
            description: fileInfo.description,
            ...(uploadFile.duration && { duration: uploadFile.duration }), // 如果有视频时长则添加
            ...(uploadFile.isAvi && { isAvi: true }) // 如果是AVI格式则标记
        }

        // 初始化上传
        const initRes = await initUpload(uploadParams)

        if (!initRes) {
            throw new Error('初始化上传失败')
        }

        const { objectName, uploadId, uploadUrls, previewUrl } = initRes
        uploadingFiles.value[fileIndex].uploadId = uploadId
        uploadingFiles.value[fileIndex].objectName = objectName
        uploadingFiles.value[fileIndex].ossPath = previewUrl

        // 分片上传
        for (let i = 0; i < totalChunks; i++) {
            const start = i * chunkSize
            const end = Math.min(start + chunkSize, uploadFile.file.size)
            const chunk = uploadFile.file.slice(start, end)

            await uploadChunk(chunk, uploadUrls[i], fileIndex, i + 1, totalChunks)
        }

        // 完成上传（只有分片文件需要调用）
        if (totalChunks > 1) {
            await completeUpload({
                objectName,
                uploadId
            })
        }

        // 更新文件状态为成功
        uploadingFiles.value[fileIndex].status = 'success'
        uploadingFiles.value[fileIndex].progress = 100
        console.log('uploadingFiles.value__-', uploadingFiles.value)
    } catch (error) {
        console.error('文件上传失败:', error)
        uploadingFiles.value[fileIndex].status = 'error'
        throw error
    }
}

/**
 * 计算文件MD5
 */
const calculateFileMD5 = (file: File): Promise<string> => {
    return new Promise((resolve, reject) => {
        const spark = new SparkMD5.ArrayBuffer()
        const fileReader = new FileReader()
        const chunkSize = 10 * 1024 * 1024 // 10MB
        let currentChunk = 0
        const totalChunks = Math.ceil(file.size / chunkSize)

        const loadNext = () => {
            const start = currentChunk * chunkSize
            const end = Math.min(start + chunkSize, file.size)
            const chunk = file.slice(start, end)

            fileReader.onload = (e) => {
                spark.append(e.target?.result as ArrayBuffer)
                currentChunk++

                if (currentChunk < totalChunks) {
                    loadNext()
                } else {
                    resolve(spark.end())
                }
            }

            fileReader.onerror = reject
            fileReader.readAsArrayBuffer(chunk)
        }

        loadNext()
    })
}

/**
 * 上传分片
 */
const uploadChunk = async (
    chunk: Blob,
    uploadUrl: string,
    fileIndex: number,
    currentChunk: number,
    totalChunks: number
) => {
    try {
        await axios.put(uploadUrl, chunk, {
            headers: {
                'Content-Type': 'application/octet-stream'
            },
            onUploadProgress: (progressEvent) => {
                const chunkProgress = Math.round(
                    (progressEvent.loaded * 100) / (progressEvent.total || 1)
                )
                const overallProgress = Math.floor(
                    ((currentChunk - 1 + chunkProgress / 100) / totalChunks) * 100
                )

                uploadingFiles.value[fileIndex].currentChunk = currentChunk
                uploadingFiles.value[fileIndex].progress = Math.min(overallProgress, 100)
            }
        })
    } catch (error) {
        console.error(`分片 ${currentChunk} 上传失败:`, error)
        throw error
    }
}

/**
 * 自动开始上传（选择文件后立即上传）
 */
const startAutoUpload = async () => {
    if (selectedFiles.value.length === 0) {
        return
    }

    try {
        uploading.value = true
        progressModalVisible.value = true

        // 获取需要上传的文件（状态为waiting的文件）
        const filesToUpload = selectedFiles.value.filter(
            (file) => !file.status || file.status === 'waiting'
        )

        if (filesToUpload.length === 0) {
            return
        }
        console.log('selectedFiles.value', selectedFiles.value)

        // 初始化上传文件列表
        uploadingFiles.value = selectedFiles.value.map((file) => ({
            ...file,
            status: file.status || 'waiting',
            progress: file.progress || 0,
            currentChunk: file.currentChunk || 0,
            totalChunks: file.totalChunks || 0
        }))

        // 逐个上传文件
        let successCount = 0
        let failCount = 0

        for (let i = 0; i < uploadingFiles.value.length; i++) {
            if (uploadingFiles.value[i].status === 'waiting') {
                try {
                    await uploadSingleFile(uploadingFiles.value[i], i)
                    successCount++
                } catch (error) {
                    failCount++
                    console.error(`文件 ${uploadingFiles.value[i].name} 上传失败:`, error)
                }
            }
        }

        // 根据上传结果显示不同的消息
        if (failCount === 0) {
            ElMessage.success('所有文件上传成功！')
            progressModalVisible.value = false
            console.log('uploadingFiles', uploadingFiles.value.length)
        } else if (successCount > 0) {
            ElMessage.warning(`${successCount} 个文件上传成功，${failCount} 个文件上传失败`)
        } else {
            throw new Error('所有文件上传失败')
        }

        // 清空已上传的文件
        selectedFiles.value = selectedFiles.value.filter((file) => file.status !== 'success')

        if (selectedFiles.value.length === 0) {
            progressModalVisible.value = false
        }
    } catch (error) {
        ElMessage.error('文件上传失败，请重试')
        console.error('Upload error:', error)
    } finally {
        uploading.value = false
    }
}

/**
 * 批量上传处理函数
 */
const handleBatchUpload = async () => {
    if (selectedFiles.value.length === 0) {
        ElMessage.warning('请先选择要上传的文件')
        return
    }

    if (selectedCategoryIds.value.length === 0) {
        ElMessage.warning('请先选择文件分类')
        return
    }
    console.log('selectedCategoryIds.value', selectedCategoryIds.value);

    try {
        // 如果有文件上传成功，调用batchAdd接口
        if (selectedFiles.value.length > 0) {
            try {
                const batchData = {
                    fileList: uploadingFiles.value,
                    categoryIdList: selectedCategoryIds.value
                }

                console.log('调用batchAdd接口，传入数据:', batchData)
                await batchAdd(batchData)

                // 批量添加成功后清空文件
                selectedFiles.value = []
                if (fileInput.value) {
                    fileInput.value.value = ''
                }
                // 确保无论成功还是失败都清空分类选择
                selectedCategoryIds.value = []
                // 调用子组件的清空方法
                categorySelectorRef.value?.clearSelectedCategories()
                ElMessage.success('文件批量添加成功！')
            } catch (error) {
                console.error('批量添加文件失败:', error)
                ElMessage.error('添加到文件管理系统失败，请联系管理员')
            }
        }

        // 延迟关闭进度弹窗
        setTimeout(() => {
            progressModalVisible.value = false
            // 清空uploadingFiles数组
            uploadingFiles.value = []
        }, 2000)

        // 清空已上传的文件
        selectedFiles.value = selectedFiles.value.filter((file) => file.status !== 'success')
    } catch (error) {
        ElMessage.error('文件上传失败，请重试')
        console.error('Batch upload error:', error)
    } finally {
        uploading.value = false
    }
}

/**
 * 重置表单
 */
const resetForm = () => {
    selectedFiles.value = []
    fileInfo.category = ''
    fileInfo.tags = []
    fileInfo.description = ''
    customTag.value = ''
    uploadingFiles.value = []
    progressModalVisible.value = false
    selectedCategoryIds.value = []
    // 调用子组件的清空方法
    categorySelectorRef.value?.clearSelectedCategories()
    if (fileInput.value) {
        fileInput.value.value = ''
    }
}

/**
 * 移除单个文件
 */
const removeFile = (index: number) => {
    selectedFiles.value.splice(index, 1)
    ElMessage.info('文件已移除')
}

/**
 * 清空所有文件
 */
const clearAllFiles = () => {
    selectedFiles.value = []
    if (fileInput.value) {
        fileInput.value.value = ''
    }
    ElMessage.info('已清空所有文件')
}

/**
 * 获取文件图标
 */
const getFileIcon = (fileType: string) => {
    if (fileType.includes('pdf')) return Document
    if (fileType.includes('word') || fileType.includes('document')) return Document
    if (fileType.includes('excel') || fileType.includes('sheet')) return Document
    if (fileType.includes('powerpoint') || fileType.includes('presentation')) return Document
    if (fileType.startsWith('image/')) return Picture
    if (fileType.startsWith('video/')) return VideoPlay
    if (fileType.startsWith('audio/')) return Headset
    if (fileType.startsWith('text/') || fileType === 'application/json' || fileType === 'application/xml') return Document
    if (fileType.includes('zip') || fileType.includes('rar') || fileType.includes('7z')) return Files
    return Document
}

/**
 * 获取文件图标样式类
 */
const getFileIconClass = (fileType: string) => {
    if (fileType.includes('pdf')) return 'file-icon-pdf'
    if (fileType.includes('word') || fileType.includes('document')) return 'file-icon-doc'
    if (fileType.includes('excel') || fileType.includes('sheet')) return 'file-icon-excel'
    if (fileType.includes('powerpoint') || fileType.includes('presentation')) return 'file-icon-ppt'
    if (fileType.startsWith('image/')) return 'file-icon-image'
    if (fileType.startsWith('video/')) return 'file-icon-video'
    if (fileType.startsWith('audio/')) return 'file-icon-audio'
    if (fileType.startsWith('text/') || fileType === 'application/json' || fileType === 'application/xml') return 'file-icon-text'
    if (fileType.includes('zip') || fileType.includes('rar') || fileType.includes('7z')) return 'file-icon-archive'
    return 'file-icon-default'
}

/**
 * 格式化文件大小
 */
const formatFileSize = (bytes: number): string => {
    if (bytes === 0) return '0 B'
    const k = 1024
    const sizes = ['B', 'KB', 'MB', 'GB']
    const i = Math.floor(Math.log(bytes) / Math.log(k))
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

/**
 * 格式化视频时长
 */
const formatDuration = (seconds: number): string => {
    if (!seconds || seconds <= 0) return ''

    const hours = Math.floor(seconds / 3600)
    const minutes = Math.floor((seconds % 3600) / 60)
    const secs = Math.floor(seconds % 60)

    if (hours > 0) {
        return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
    } else {
        return `${minutes}:${secs.toString().padStart(2, '0')}`
    }
}

/**
 * 获取文件类型文本
 */
const getFileTypeText = (fileType: string): string => {
    if (fileType.includes('pdf')) return 'PDF'
    if (fileType.includes('word') || fileType.includes('document')) return 'Word'
    if (fileType.includes('excel') || fileType.includes('sheet')) return 'Excel'
    if (fileType.includes('powerpoint') || fileType.includes('presentation')) return 'PPT'
    if (fileType.startsWith('image/')) return '图片'
    if (fileType.startsWith('video/')) return '视频'
    if (fileType.startsWith('audio/')) return '音频'
    if (fileType === 'text/plain') return 'TXT'
    if (fileType === 'text/html') return 'HTML'
    if (fileType === 'text/css') return 'CSS'
    if (fileType === 'text/javascript') return 'JS'
    if (fileType === 'application/json') return 'JSON'
    if (fileType === 'text/xml' || fileType === 'application/xml') return 'XML'
    if (fileType === 'text/csv') return 'CSV'
    if (fileType === 'text/markdown') return 'MD'
    if (fileType.startsWith('text/')) return '文本'
    if (fileType.includes('zip')) return 'ZIP'
    if (fileType.includes('rar')) return 'RAR'
    if (fileType.includes('7z')) return '7Z'
    return '文件'
}
</script>

<style scoped lang="scss">
.file-upload-container {
    display: flex;
    gap: 24px;
    padding: 24px;
    min-height: calc(100vh - 120px);
}

.upload-section {
    flex: 1;
    border-radius: 8px;
    padding: 24px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.info-section {
    width: 400px;
    border-radius: 8px;
    padding: 24px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.upload-header,
.info-header {
    margin-bottom: 24px;

    h3 {
        margin: 0;
        font-size: 18px;
        font-weight: 600;
    }
}

.upload-area {
    border: 2px dashed #dcdfe6;
    border-radius: 8px;
    padding: 48px 24px;
    text-align: center;
    transition: all 0.3s ease;
    margin-bottom: 24px;

    &:hover {
        border-color: #409eff;
    }
}

.upload-icon {
    margin-bottom: 16px;
}

.upload-text {
    margin-bottom: 24px;

    .main-text {
        font-size: 16px;
        font-weight: 500;
        margin: 0 0 8px 0;
    }

    .sub-text {
        font-size: 14px;
        margin: 0 0 4px 0;
    }

    .size-limit {
        font-size: 12px;
        margin: 0;
    }
}

.selected-files {
    margin-bottom: 24px;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);

    .files-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 16px 20px;
        border-radius: 8px 8px 0 0;

        h4 {
            margin: 0;
            font-size: 16px;
            font-weight: 600;
        }
    }

    .files-list {
        max-height: 300px;
        overflow-y: auto;

        .file-item {
            display: flex;
            align-items: center;
            padding: 12px 20px;
            border-bottom: 1px solid #e6e8ec;
            transition: background-color 0.3s;

            &:last-child {
                border-bottom: none;
            }

            .file-icon {
                margin-right: 12px;

                &.file-icon-pdf {
                    color: #f56c6c;
                }

                &.file-icon-doc {
                    color: #409eff;
                }

                &.file-icon-excel {
                    color: #67c23a;
                }

                &.file-icon-ppt {
                    color: #e6a23c;
                }

                &.file-icon-image {
                    color: #909399;
                }

                &.file-icon-video {
                    color: #f56c6c;
                }

                &.file-icon-audio {
                    color: #e6a23c;
                }

                &.file-icon-text {
                    color: #67c23a;
                }

                &.file-icon-archive {
                    color: #909399;
                }

                &.file-icon-default {
                    color: #909399;
                }
            }

            .file-info {
                flex: 1;
                min-width: 0;

                .file-name {
                    font-size: 14px;
                    font-weight: 500;
                    margin-bottom: 4px;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                }

                .file-meta {
                    display: flex;
                    gap: 12px;
                    font-size: 12px;
                    color: #909399;
                    flex-wrap: wrap;

                    .file-size,
                    .file-type,
                    .file-duration,
                    .file-format {
                        &::before {
                            content: '';
                            display: inline-block;
                            width: 4px;
                            height: 4px;
                            background-color: #c0c4cc;
                            border-radius: 50%;
                            margin-right: 6px;
                            vertical-align: middle;
                        }

                        &:first-child::before {
                            display: none;
                        }
                    }

                    .file-duration {
                        color: #409eff;
                        font-weight: 500;
                    }

                    .file-format {
                        background: #e6a23c;
                        color: white;
                        padding: 1px 4px;
                        border-radius: 2px;
                        font-size: 10px;

                        &::before {
                            display: none;
                        }
                    }
                }

                .file-progress {
                    margin-top: 8px;
                }

                .file-status {
                    margin-left: 8px;
                    font-size: 12px;

                    &.status-waiting {
                        color: #909399;
                    }

                    &.status-uploading {
                        color: #409eff;
                    }

                    &.status-success {
                        color: #67c23a;
                    }

                    &.status-error {
                        color: #f56c6c;
                    }
                }
            }

            .file-actions {
                margin-left: 12px;

                .el-button {
                    color: #909399;

                    &:hover {
                        color: #f56c6c;
                    }
                }
            }
        }
    }
}

.upload-notice {
    .notice-list {
        margin: 0;

        li {
            margin-bottom: 4px;
            font-size: 14px;

            &:last-child {
                margin-bottom: 0;
            }
        }
    }
}

.form-item {
    margin-bottom: 24px;
}

.form-label {
    display: block;
    margin-bottom: 8px;
    font-size: 14px;
    font-weight: 500;

    &.required::after {
        content: '*';
        color: #f56c6c;
        margin-left: 4px;
    }
}

.tag-container {

    .common-tags,
    .custom-tags {
        margin-bottom: 12px;

        &:last-child {
            margin-bottom: 0;
        }
    }

    .tag-label {
        display: inline-block;
        margin-bottom: 8px;
        font-size: 13px;
    }

    .selected-tags {
        margin-top: 16px;
        padding: 12px;
        background: #f8f9fa;
        border-radius: 6px;
        border: 1px solid #e9ecef;
    }

    .selected-tags-list {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        margin-top: 8px;
    }

    .selected-tag-item {
        margin: 0;
    }

    .tag-item {
        margin-right: 8px;
        margin-bottom: 8px;
        cursor: pointer;
        transition: all 0.3s ease;

        &:hover {
            transform: translateY(-1px);
        }
    }
}

/* 分类树样式 */
.category-tree {
    border: 1px solid #dcdfe6;
    border-radius: 6px;
    padding: 12px;
    max-height: 200px;
    overflow-y: auto;
    background: #fff;

    :deep(.el-tree-node__content) {
        height: 32px;
        line-height: 32px;
        font-size: 14px;

        &:hover {
            background-color: #f5f7fa;
        }
    }

    :deep(.el-tree-node__label) {
        font-size: 14px;
        color: #303133;
    }

    :deep(.el-checkbox) {
        margin-right: 8px;
    }

    :deep(.el-tree-node__expand-icon) {
        color: #c0c4cc;
        font-size: 12px;
    }

    :deep(.el-tree-node__expand-icon.expanded) {
        transform: rotate(90deg);
    }
}

/* 已选分类样式 */
.selected-categories {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px;
    background: #f8f9fa;
    border-radius: 6px;
    border: 1px solid #e9ecef;
    min-height: 44px;
    align-items: flex-start;
    align-content: flex-start;
}

.category-tag {
    margin: 0;
    font-size: 13px;
    padding: 4px 8px;
    border-radius: 4px;
    transition: all 0.3s ease;

    &:hover {
        transform: translateY(-1px);
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    }

    .el-tag__close {
        margin-left: 6px;
        font-size: 12px;
    }
}

.action-buttons {
    display: flex;
    gap: 12px;
    justify-content: flex-end;
    margin-top: 32px;

    .el-button {
        min-width: 100px;
    }
}

/* 上传进度弹窗样式 */
.upload-progress-container {
    padding: 20px 0;
}

.file-name-cell {
    max-width: 160px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 14px;
}

.file-type-info {
    font-size: 12px;
    line-height: 1.4;

    .duration-text {
        color: #409eff;
        font-weight: 500;
        margin-top: 2px;
    }

    .avi-badge {
        background: #e6a23c;
        color: white;
        padding: 1px 4px;
        border-radius: 2px;
        font-size: 10px;
        margin-top: 2px;
        display: inline-block;
    }
}

.progress-cell {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.progress-text {
    font-size: 12px;
    color: #606266;
    font-weight: 500;
}

.status-text {
    font-size: 11px;
    text-align: center;

    &.status-waiting {
        color: #909399;
    }

    &.status-uploading {
        color: #409eff;
    }

    &.status-success {
        color: #67c23a;
    }

    &.status-error {
        color: #f56c6c;
    }
}

.dialog-footer {
    text-align: center;
}

/* 进度条样式优化 */
.el-progress {
    margin-bottom: 4px;
}

.el-progress__text {
    font-size: 12px !important;
}

// 响应式设计
@media (max-width: 1200px) {
    .file-upload-container {
        flex-direction: column;
    }

    .info-section {
        width: 100%;
    }
}

@media (max-width: 768px) {
    .file-upload-container {
        padding: 16px;
        gap: 16px;
    }

    .upload-section,
    .info-section {
        padding: 16px;
    }

    .upload-area {
        padding: 32px 16px;
    }

    .action-buttons {
        flex-direction: column;

        .el-button {
            width: 100%;
        }
    }
}
</style>
